
#include "serial.h"

#if ( USART1_ENABLE==1 )
	#define USART1_TX_BUFF_SIZE 		1024
	#define USART1_RX_BUFF_SIZE 		1024
	#define USART1_TX_DMA_BUFF_SIZE	512
	#define USART1_RX_DMA_BUFF_SIZE 128
	static uint8_t usart1_tx_buff[USART1_TX_BUFF_SIZE];
	static uint8_t usart1_rx_buff[USART1_RX_BUFF_SIZE];
	static uint8_t usart1_tx_dma_buff[USART1_TX_DMA_BUFF_SIZE];
	static uint8_t usart1_rx_dma_buff[USART1_RX_DMA_BUFF_SIZE];
	static awesome_usart awesome_usart1;   /// 串口数据操作对象
	extern UART_HandleTypeDef huart1;
	Serial serial1;
#endif

#if ( USART2_ENABLE==1 )
	#define USART2_TX_BUFF_SIZE 		1024
	#define USART2_RX_BUFF_SIZE 		1024
	#define USART2_TX_DMA_BUFF_SIZE	512
	#define USART2_RX_DMA_BUFF_SIZE 128
	static uint8_t usart2_tx_buff[USART2_TX_BUFF_SIZE];
	static uint8_t usart2_rx_buff[USART2_RX_BUFF_SIZE];
	static uint8_t usart2_tx_dma_buff[USART2_TX_DMA_BUFF_SIZE];
	static uint8_t usart2_rx_dma_buff[USART2_RX_DMA_BUFF_SIZE];
	static awesome_usart awesome_usart2;
	extern UART_HandleTypeDef huart2;
	Serial serial2;
#endif

#if ( USART3_ENABLE==1 )
	#define USART3_TX_BUFF_SIZE 		1024
	#define USART3_RX_BUFF_SIZE 		1024
	#define USART3_TX_DMA_BUFF_SIZE	512
	#define USART3_RX_DMA_BUFF_SIZE 128
	static uint8_t usart3_tx_buff[USART3_TX_BUFF_SIZE];
	static uint8_t usart3_rx_buff[USART3_RX_BUFF_SIZE];
	static uint8_t usart3_tx_dma_buff[USART3_TX_DMA_BUFF_SIZE];
	static uint8_t usart3_rx_dma_buff[USART3_RX_DMA_BUFF_SIZE];
	static awesome_usart awesome_usart3;
	extern UART_HandleTypeDef huart3;
	
	Serial serial3;
#endif

#if ( USB_USART_ENABLE==1 )
	#define USB_TX_BUFF_SIZE 		1024
	#define USB_RX_BUFF_SIZE 		1024
	#define USB_TX_DMA_BUFF_SIZE	512
	#define USB_RX_DMA_BUFF_SIZE 128
	static uint8_t usb_tx_buff[USB_TX_BUFF_SIZE];
	static uint8_t usb_rx_buff[USB_RX_BUFF_SIZE];
	static uint8_t usb_tx_dma_buff[USB_TX_DMA_BUFF_SIZE];
	static awesome_usart awesome_usart_usb;	
	extern USBD_HandleTypeDef hUsbDeviceFS;
	
	Serial usb_serial;
#endif

Serial* serials[USART_MAX_NUM] = { NULL, NULL, NULL };

/// 收发处理函数，上层定时调用，用户可以覆盖
/// 判断发送数据是否有效，有效则发送新的一帧数据
/// 读取串口接收缓冲区中的数据进行处理
__weak void serial_process_callback(void)
{	
	uint8_t i = 0;
	for( ; i<USART_MAX_NUM; ++i )
	{
		if( serials[i]!=NULL )
		{
			SERIAL_ID id = serials[i]->id;
			switch(id)
			{
				case SERIAL_ID_1:
					break;
				case SERIAL_ID_2:
					break;
				case SERIAL_ID_3:
					break;
				case SERIAL_ID_USB:
					break;
				default:
					break;
			}	
			
			open_usart_send(serials[i]);			
		}
	}
}

/// 通过串口实例获取serial对象，用户可根据实际使用串口进行修改
static Serial* get_serial(void* huart)
{
	UART_HandleTypeDef* phuart = (UART_HandleTypeDef*)huart;
	
	#if ( USART1_ENABLE==1 )
		if( &huart1==phuart && serial1.huart==phuart )
			return &serial1;
	#endif
	
	#if ( USART2_ENABLE==1 )
		if( &huart2==phuart && serial2.huart==phuart )
			return &serial2;
	#endif
		
	#if ( USART3_ENABLE==1 )
		if( &huart3==phuart && serial3.huart==phuart )
			return &serial3;
	#endif
		
	#if ( USB_USART_ENABLE==1 )
		if( &hUsbDeviceFS==(USBD_HandleTypeDef*)huart && usb_serial.huart==huart)
			return &usb_serial;
	#endif
	return NULL;
}

/// 通过串口实例获取serial对象，用户可根据实际使用串口进行修改
__inline static Serial* get_serial_by_id(SERIAL_ID id)
{
	
	#if ( USART1_ENABLE==1 )
		if( id==SERIAL_ID_1 )
			return &serial1;
	#endif
	
	#if ( USART2_ENABLE==1 )
		if( id==SERIAL_ID_2 )
			return &serial2;
	#endif
		
	#if ( USART3_ENABLE==1 )
		if( id==SERIAL_ID_3 )
			return &serial3;
	#endif
		
	#if ( USB_USART_ENABLE==1 )
		if( id==SERIAL_ID_USB )
			return &usb_serial;
	#endif
	return NULL;
}

/// 初始化串口资源
void serial_init(void)
{
#if ( USART1_ENABLE==1 )
	awesome_usart_init(&awesome_usart1, usart1_rx_buff, USART1_RX_BUFF_SIZE, usart1_tx_buff, USART1_TX_BUFF_SIZE);
	serial1.id = SERIAL_ID_1;
	serial1.send_status = SERIAL_SEND_STATUS_NONE;
	serial1.receive_status = SERIAL_SEND_STATUS_NONE;
	serial1.huart = (void*)&huart1;
	serial1.pawesome_usart = &awesome_usart1;
	serial1.ptx = usart1_tx_buff;
	serial1.prx = usart1_rx_buff;
	serial1.pdmatx = usart1_tx_dma_buff;
	serial1.pdmarx = usart1_rx_dma_buff;
	serial1.tx_max_size = USART1_TX_BUFF_SIZE;
	serial1.rx_max_size = USART1_RX_BUFF_SIZE;
	serial1.tx_max_dma_size = USART1_TX_DMA_BUFF_SIZE;
	serial1.rx_max_dma_size = USART1_RX_DMA_BUFF_SIZE;
	serials[0] = &serial1;
	open_serial_receive(&serial1);
#endif
	
#if ( USART2_ENABLE==1 )
	awesome_usart_init(&awesome_usart2, usart2_rx_buff, USART2_RX_BUFF_SIZE, usart2_tx_buff, USART2_TX_BUFF_SIZE);
	serial2.id = SERIAL_ID_2;
	serial2.send_status = SERIAL_SEND_STATUS_NONE;
	serial2.receive_status = SERIAL_SEND_STATUS_NONE;
	serial2.huart = (void*)&huart2;
	serial2.pawesome_usart = &awesome_usart2;
	serial2.ptx = usart2_tx_buff;
	serial2.prx = usart2_rx_buff;
	serial2.pdmatx = usart2_tx_dma_buff;
	serial2.pdmarx = usart2_rx_dma_buff;
	serial2.tx_max_size = USART2_TX_BUFF_SIZE;
	serial2.rx_max_size = USART2_RX_BUFF_SIZE;
	serial2.tx_max_dma_size = USART2_TX_DMA_BUFF_SIZE;
	serial2.rx_max_dma_size = USART2_RX_DMA_BUFF_SIZE;
	serials[1] = &serial2;
	open_serial_receive(&serial2);
#endif
	
#if ( USART3_ENABLE==1 )
	awesome_usart_init(&awesome_usart3, usart3_rx_buff, USART3_RX_BUFF_SIZE, usart3_tx_buff, USART3_TX_BUFF_SIZE);
	serial3.id = SERIAL_ID_3;
	serial3.send_status = SERIAL_SEND_STATUS_NONE;
	serial3.receive_status = SERIAL_SEND_STATUS_NONE;
	serial3.huart = (void*)&huart3;
	serial3.pawesome_usart = &awesome_usart3;
	serial3.ptx = usart3_tx_buff;
	serial3.prx = usart3_rx_buff;
	serial3.pdmatx = usart3_tx_dma_buff;
	serial3.pdmarx = usart3_rx_dma_buff;
	serial3.tx_max_size = USART3_TX_BUFF_SIZE;
	serial3.rx_max_size = USART3_RX_BUFF_SIZE;
	serial3.tx_max_dma_size = USART3_TX_DMA_BUFF_SIZE;
	serial3.rx_max_dma_size = USART3_RX_DMA_BUFF_SIZE;
	serials[2] = &serial3;
	open_serial_receive(&serial3);
#endif

#if ( USB_USART_ENABLE==1 )
	awesome_usart_init(&awesome_usart_usb, usb_rx_buff, USB_RX_BUFF_SIZE, usb_tx_buff, USB_TX_BUFF_SIZE);
	usb_serial.id = SERIAL_ID_USB;
	usb_serial.send_status = SERIAL_SEND_STATUS_NONE;
	usb_serial.receive_status = SERIAL_SEND_STATUS_NONE;
	usb_serial.huart = (void*)&hUsbDeviceFS;
	usb_serial.pawesome_usart = &awesome_usart_usb;
	usb_serial.ptx = usb_tx_buff;
	usb_serial.prx = usb_rx_buff;
	usb_serial.pdmatx = usb_tx_dma_buff;
	usb_serial.pdmarx = NULL;
	usb_serial.tx_max_size = USB_TX_BUFF_SIZE;
	usb_serial.rx_max_size = USB_RX_BUFF_SIZE;
	usb_serial.tx_max_dma_size = USB_TX_DMA_BUFF_SIZE;
	usb_serial.rx_max_dma_size = 0;
	serials[3] = &usb_serial;
#endif
}

/// 开启串口接收，DMA+空闲中断方式
HAL_StatusTypeDef open_serial_receive(Serial* ps)
{
	HAL_StatusTypeDef res = HAL_ERROR;
	
	if( ps->id==SERIAL_ID_USB ) return HAL_OK;

	res = HAL_UART_Receive_DMA(ps->huart, ps->pdmarx, ps->rx_max_dma_size);
	
	return res;
}

/// 开启串口发送，DMA方式发送，发送完成，中断中置位发送完成标志
HAL_StatusTypeDef open_usart_send(Serial* ps)
{
	HAL_StatusTypeDef res = HAL_ERROR;
	
	if( ps->id==SERIAL_ID_USB )
	{
		uint32_t len = ps->pawesome_usart->low_get_write_buff(ps->pawesome_usart, ps->pdmatx, ps->tx_max_dma_size);
		if( len>0 )
		{
			CDC_Transmit_FS(ps->pdmatx, len);
		}
	}
	
	if( ps->send_status!=SERIAL_SEND_STATUS_SENDING )
	{
		uint32_t len = ps->pawesome_usart->low_get_write_buff(ps->pawesome_usart, ps->pdmatx, ps->tx_max_dma_size);
		if( len>0 )
		{
			res = HAL_UART_Transmit_DMA(ps->huart, ps->pdmatx, len);
			if( res==HAL_OK )
			{
				ps->send_status = SERIAL_SEND_STATUS_SENDING;
			}
		}
	}
	return res;
}


/// 串口收发上层调用函数 ///
/// 往串口发送缓冲区中写入数据
void serial_write(SERIAL_ID id, uint8_t* data, uint32_t len)
{
	Serial* ps = get_serial_by_id(id);
	ps->pawesome_usart->writes(ps->pawesome_usart, data, len);
}

/// 读取串口接收数据
uint32_t serial_read(SERIAL_ID id, uint8_t* data, uint32_t len)
{
	Serial* ps = get_serial_by_id(id);
	return ps->pawesome_usart->reads(ps->pawesome_usart, data, len);
}


////////////////////////////////////////////////////////////////////////////////
///           中断函数调用           ///

/// 串口发送中断完成
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{	
	Serial* ps = get_serial((void*)huart);
	
	ps->send_status = SERIAL_SEND_STATUS_SUCESS;
	
}

/// 串口接收中断调用(接收缓冲区被填满时调用)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	Serial* ps = get_serial((void*)huart);
	
	if( huart->hdmarx!=NULL && ps!=NULL )
	{
		ps->pawesome_usart->low_set_read_buff(ps->pawesome_usart, ps->pdmarx, ps->rx_max_dma_size);
	
		open_serial_receive(ps);   /// 重新打开串口DMA接收
	}
	
}

/// 空闲中断和中断发生错误调用函数，DMA中断错误调用
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
	uint32_t dma_len = 0;
	Serial* ps = get_serial((void*)huart);
	
	if( huart->hdmarx!=NULL && ps!=NULL )
	{
		dma_len = ps->rx_max_dma_size - huart->hdmarx->Instance->CNDTR;
		if( dma_len>0 && dma_len!=ps->rx_max_dma_size )   // DMA接收缓冲区没有满，则选择不定长处理
			ps->pawesome_usart->low_set_read_buff(ps->pawesome_usart, ps->pdmarx, dma_len);
	}
	
	open_serial_receive(ps);   /// 重新打开串口DMA接收
		
}

// usb接收调用
void usb_receive_callback(uint8_t* data, uint32_t len)
{
#if ( USB_USART_ENABLE==1 )
	usb_serial.pawesome_usart->low_set_read_buff(usb_serial.pawesome_usart, data, len);
#endif
}


